/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "can.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "rtthread.h"
#include "ul_ringbuffer.h"
#include "ul_w25qxx.h"
#include "ul_softwarespi.h"
#include "ul_pid.h"
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
struct mq_data
{
    uint32_t a;
    uint32_t b;
};

rt_sem_t test_sem = NULL;
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */
static struct rt_thread led_thread;
rt_thread_t preceive_thread = RT_NULL;
rt_thread_t key2_thread = RT_NULL;
rt_uint8_t rt_led_thread_stack[128];


/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */

void receive_task_entry(void *parameter)
{
    rt_err_t uwRet = RT_EOK;
    
	while(1)
	{
        HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
        rt_thread_delay(200);
	}
}



void delay_xxus(void)
{
    for(int i=0;i<10;i++);
}
    
void scl_write(uint8_t pin_state)
{
    if (pin_state == 1)
    {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_SET);
    }
    else
    {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_10, GPIO_PIN_RESET);
    }
}
void sda_write(uint8_t pin_state)
{
    if (pin_state == 1)
    {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_SET);
    }
    else
    {
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_11, GPIO_PIN_RESET);
    }
}

ul_swspi_t swspi;
ul_dev_w25qxx_t w25q64;
void cs_write(ul_uint8_t pin_state)
{
    HAL_GPIO_WritePin(SPI_CS_GPIO_Port, SPI_CS_Pin, pin_state);
}

void sck_write(ul_uint8_t pin_state)
{
    HAL_GPIO_WritePin(SPI_SCK_GPIO_Port, SPI_SCK_Pin, pin_state);
}

void mosi_write(ul_uint8_t pin_state)
{
    HAL_GPIO_WritePin(SPI_MOSI_GPIO_Port, SPI_MOSI_Pin, pin_state);
}

ul_uint8_t miso_read(void)
{
    return HAL_GPIO_ReadPin(SPI_MISO_GPIO_Port, SPI_MISO_Pin);
}

ul_uint8_t spi_rwbyte(ul_uint8_t wbyte)
{
//    uint8_t rxdata;
//    //HAL_SPI_TransmitReceive(&hspi1, &wbyte, &rxdata, 1, 1000);
//    return rxdata;
            
    return ul_swspi_rwbyte(&swspi, wbyte);
}

void key_task_entry(void *parameter)
{
    rt_err_t uwRet = RT_EOK;

    swspi.miso_read = miso_read;
    swspi.mosi_write = mosi_write;
    swspi.sck_write = sck_write;
    ul_swspi_init(&swspi, 0);
    
    w25q64.spi_rwbyte = spi_rwbyte;
    w25q64.cs_write = cs_write;
    ul_w25qxx_init(&w25q64,64);
    unsigned char buff[10] = {0};
    rt_enter_critical();
    rt_kprintf("ID = %X\n",ul_w25qxx_checkid(&w25q64));
    ul_w25qxx_read(&w25q64, 0, buff, 5);
    rt_kprintf("buff = %s\n",buff);
    ul_w25qxx_write(&w25q64,0, "FFFF", 5);
    ul_w25qxx_read(&w25q64,0, buff, 5);
    rt_kprintf("buff = %s\n",buff);
    rt_exit_critical();
	while(1)
	{
        
		rt_thread_delay(20);
	}
}

#define RING_BUFFER_LEN        20

static struct ul_ringbuffer *rb;
static char  *str = "Hello,World";

static void consumer_thread_entry(void *arg)
{
    rt_uint8_t ch[20];

    while (1)
    {
        if (0 != ul_ringbuffer_data_len(rb))
        {
            ul_ringbuffer_get(rb, ch, ul_ringbuffer_data_len(rb));
            
            rt_kprintf("[Consumer] <- %s\n", ch);
        }
        rt_thread_mdelay(1);
    }
}

static void ringbuffer_sample(int argc, char** argv)
{
    rt_thread_t tid;
    rt_uint16_t i = 0;

    rb = ul_ringbuffer_create(RING_BUFFER_LEN);
    if (rb == RT_NULL)
    {
        rt_kprintf("Can't create ringbffer");
        return;
    }

    tid = rt_thread_create("consumer", consumer_thread_entry, RT_NULL,
                           1024, RT_THREAD_PRIORITY_MAX/3, 20);
    if (tid == RT_NULL)
    {
        ul_ringbuffer_destroy(rb);
    }
    rt_thread_startup(tid);


    while (str[i] != '\0')
    {
        rt_kprintf("[Producer] -> %c\n", str[i]);
        ul_ringbuffer_putchar(rb, str[i++]);
        rt_thread_mdelay(100);
    }

    for (uint8_t j = 0; j<5;j++)
    {
        rt_kprintf("[Producer] -> %s\n", str);
        ul_ringbuffer_put(rb, str, rt_strlen(str));
        rt_thread_mdelay(100);
    }
    rt_thread_delete(tid);
    ul_ringbuffer_destroy(rb);
    
}

MSH_CMD_EXPORT(ringbuffer_sample, Start a producer and a consumer with a ringbuffer);
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
    rt_base_t level;
    level = rt_hw_interrupt_disable();
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_CAN_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  /* USER CODE BEGIN 2 */
  #if 0
    rt_thread_init(&led_thread,
                    "led",
                    led_task_entry,
                    RT_NULL,
                    &rt_led_thread_stack[0],
                    sizeof(rt_led_thread_stack),
                    3,
                    20);
                    
    rt_thread_startup(&led_thread);
	#else
    
    
    
    
    preceive_thread =
    rt_thread_create("receive",
                     receive_task_entry,
                     RT_NULL,
                     512,
                     3,
                     20);
                     
    if (preceive_thread != NULL)
    {
        rt_thread_startup(preceive_thread);
        rt_kprintf("receive_thread�����ɹ���\n");
    }
    
    key2_thread =
    rt_thread_create("key",
                     key_task_entry,
                     RT_NULL,
                     1500,
                     2,
                     20);
                     
    if (key2_thread != NULL)
    {
        rt_thread_startup(key2_thread);
        rt_kprintf("key2_thread�����ɹ���\n");
    }
    #endif
	rt_hw_interrupt_enable(level);
    return 0;   // ͨ�� LR �Ĵ���ָ�������ӵ�ַ�˳�
                // �߳�ջ��Ӧ LR �Ĵ����������� rt_thread_exit()��������rt_thread_exit ������ main �߳�ռ�õ��ڴ�ռ䶼�ͷŵ�

  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
        rt_kprintf("Hello RT_Thread!!!\n");
        rt_thread_delay(2000);
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  Period elapsed callback in non blocking mode
  * @note   This function is called  when TIM4 interrupt took place, inside
  * HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
  * a global variable "uwTick" used as application time base.
  * @param  htim : TIM handle
  * @retval None
  */
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
  /* USER CODE BEGIN Callback 0 */

  /* USER CODE END Callback 0 */
  if (htim->Instance == TIM4)
  {
    HAL_IncTick();
  }
  /* USER CODE BEGIN Callback 1 */

  /* USER CODE END Callback 1 */
}

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
